package com.eleaf.adbb.template;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import com.eleaf.adbb.exception.ResourcesException;
import com.eleaf.adbb.model.DefaultNameGenerater;
import com.eleaf.adbb.model.LayoutType;
import com.eleaf.adbb.model.NameGenerater;
import com.eleaf.adbb.util.BaseUtil;

/**
 * Javal类基础模板
 * 
 * @author Eleaf
 * 
 */
public class ClassTemplate {

	private String packagePath;
	private String className;
	private String superClassName, superInterfaceNames, annotation = "";
	private List<String> imports;
	private List<VariableTemplate> variables;
	private List<MethodTemplate> methods;

	private LayoutType layoutType;
	private NameGenerater nameGenerater;

	private boolean useRoboGuice = false;

	/**
	 * 
	 * @param type 模版适用类型
	 * @param ng 命名规则生成器
	 */
	protected ClassTemplate( LayoutType type, NameGenerater ng ) {
		imports = new ArrayList<String> ();
		variables = new ArrayList<VariableTemplate> ();
		methods = new ArrayList<MethodTemplate> ();
		this.layoutType = type;
		this.nameGenerater = ng;
	}

	/**
	 * 添加多行annotation
	 * 
	 * @param annotations
	 */
	public void addAnnotation( String... annotations ) {
		for ( String line : annotations ) {
			annotation = BaseUtil.appendString ( "\n", annotation, line );
		}
	}

	/**
	 * 引入包路径
	 * 
	 * @param pacagePath
	 */
	public void addImport( String pacagePath ) {
		if ( pacagePath != null && !pacagePath.trim ().isEmpty () ) {
			imports.add ( pacagePath );
		}
	}

	/**
	 * 引入包路径
	 * 
	 * @param pacagePaths
	 */
	public void addImport( List<String> pacagePaths ) {
		if ( pacagePaths != null ) {
			for ( String pp : pacagePaths ) {
				addImport ( pp );
			}
		}
	}

	/**
	 * 设置父类名称
	 * 
	 * @param superClassName
	 */
	public void addSuperClassName( String superClassName ) {
		this.superClassName = BaseUtil.appendString ( "extends ", superClassName );
	}

	/**
	 * 声明变量
	 * 
	 * @param variables
	 */
	public void addVariable( List<VariableTemplate> variables ) {
		if ( variables != null ) {
			for ( VariableTemplate vt : variables ) {
				addVariable ( vt );
			}
		}
	}

	/**
	 * 声明变量
	 * 
	 * @param variable
	 */
	public void addVariable( VariableTemplate variable ) {
		if ( variable != null ) {
			variables.add ( variable );
			addImport ( variable.getPackagePath () );
		}
	}

	/**
	 * 声明函数
	 * 
	 * @param methods
	 */
	public void addMethod( List<MethodTemplate> methods ) {
		if ( methods != null ) {
			for ( MethodTemplate mt : methods ) {
				addMethod ( mt );
			}
		}
	}

	/**
	 * 声明函数
	 * 
	 * @param method
	 */
	public void addMethod( MethodTemplate method ) {
		if ( method != null ) {
			this.methods.add ( method );
			addImport ( method.getPackages () );
		}
	}

	/**
	 * 实现接口
	 * 
	 * @param superInterfaceName
	 */
	public void addSuperInterfaceNames( String superInterfaceName ) {
		if ( superInterfaceNames == null || superInterfaceNames.trim ().isEmpty () ) {
			superInterfaceNames = BaseUtil.appendString ( "implements ", superInterfaceName );
		} else {
			superInterfaceNames = BaseUtil.appendString ( "implements ", superInterfaceNames, ",", superInterfaceName );
		}
	}

	/**
	 * 模版构建类
	 * 
	 * @author Eleaf
	 * 
	 */
	public static class Builder {

		private ClassTemplate template;

		/**
		 * 初始化模版
		 * 
		 * @param type 模版适用类型
		 * @param useRoboGuice 是否使用RoboGuice框架
		 * @param ng 命名规则生成类
		 */
		private Builder( LayoutType type, boolean useRoboGuice, NameGenerater ng ) {
			if ( ng == null )
				ng = new DefaultNameGenerater ();
			template = new ClassTemplate ( type, ng );
			template.setUseRoboGuice ( useRoboGuice );
		}

		/**
		 * 构建模版
		 * 
		 * @param type 模版适用类型
		 * @return
		 */
		public static Builder build( LayoutType type ) {
			return build ( type, false, null );
		}

		/**
		 * 构建模版
		 * 
		 * @param type 模版适用类型
		 * @param ng 命名规则生成类
		 * @return
		 */
		public static Builder build( LayoutType type, NameGenerater ng ) {
			return build ( type, false, ng );
		}

		/**
		 * 构建模版
		 * 
		 * @param type 模版适用类型
		 * @param useRoboGuice 是否使用RoboGuice框架
		 * @return
		 */
		public static Builder build( LayoutType type, boolean useRoboGuice ) {
			return build ( type, useRoboGuice, null );
		}

		/**
		 * 构建模版
		 * 
		 * @param type 模版适用类型
		 * @param useRoboGuice 是否使用RoboGuice框架
		 * @param ng 命名规则生成类
		 */
		public static Builder build( LayoutType type, boolean useRoboGuice, NameGenerater ng ) {

			Builder template = new Builder ( type, useRoboGuice, ng );
			return template;
		}

		/**
		 * 完成模版构建
		 * 
		 * @return 所购建的模版
		 */
		public ClassTemplate commit() {
			return template;
		}

		/**
		 * 继承父类
		 * 
		 * @param cls
		 * @return
		 * @throws ResourcesException
		 */
		public Builder extendsClass( Class<?> cls ) throws ResourcesException {
			if ( cls.isPrimitive () ) {
				throw new ResourcesException ( "cannot subclass the primitive class: ", cls.getSimpleName () );
			} else if ( cls.isArray () ) {
				throw new ResourcesException ( "cannot subclass the array class: ", cls.getSimpleName () );
			} else if ( Modifier.isFinal ( cls.getModifiers () ) ) {
				throw new ResourcesException ( "cannot subclass the final class: ", cls.getSimpleName () );
			} else {
				template.addSuperClassName ( cls.getSimpleName () );
				template.addImport ( cls.getCanonicalName () );
			}
			return this;
		}

		/**
		 * 实现接口
		 * 
		 * @param clss
		 * @return
		 * @throws ResourcesException
		 */
		public Builder implementsInterface( Class<?>... clss ) throws ResourcesException {
			for ( Class<?> cls : clss ) {
				if ( cls.isInterface () ) {
					template.addSuperInterfaceNames ( cls.getSimpleName () );
					template.addImport ( cls.getCanonicalName () );
					createMethodConfig ( cls );
				} else {
					throw new ResourcesException ( cls.getSimpleName (), " is not interface" );
				}
			}
			return this;
		}

		/**
		 * 声明变量
		 * 
		 * @param variableTemplates
		 * @return
		 */
		public Builder declareVariables( VariableTemplate... variableTemplates ) {
			for ( VariableTemplate variableTemplate : variableTemplates ) {
				template.addVariable ( variableTemplate );
			}
			return this;
		}

		/**
		 * 声明函数
		 * 
		 * @param methodTemplates
		 * @return
		 */
		public Builder declareMethod( MethodTemplate... methodTemplates ) {
			for ( MethodTemplate methodTemplate : methodTemplates ) {
				template.addMethod ( methodTemplate );
			}
			return this;
		}

		/**
		 * 添加Annotation
		 * 
		 * @param annotations
		 * @return
		 */
		public Builder addAnnotation( String... annotations ) {
			template.addAnnotation ( annotations );
			return this;
		}

		public Builder useRoboGuice( boolean use ) {
			template.setUseRoboGuice ( use );
			return this;
		}

		private void createMethodConfig( Class<?> cls ) {
			Method[] mts = cls.getMethods ();
			List<MethodTemplate> methods = new ArrayList<MethodTemplate> ();
			for ( Method method : mts ) {
				MethodTemplate mt = new MethodTemplate ( method );
				methods.add ( mt );
			}
			template.addMethod ( methods );
		}

	}

	public String getPackagePath() {
		return packagePath;
	}

	public void setPackagePath( String packagePath ) {
		this.packagePath = packagePath;
	}

	public List<String> getImports() {
		return BaseUtil.removeDuplicateWithOrder ( imports );
	}

	public String getClassName() {
		if ( className == null )
			className = "";
		return className;
	}

	public void setClassName( String className ) {
		this.className = className;
	}

	public String getSuperClassName() {
		if ( superClassName == null )
			superClassName = "";
		return superClassName;
	}

	public void setSuperClassName( String superClassName ) {
		this.superClassName = superClassName;
	}

	public List<VariableTemplate> getVariables() {
		return variables;
	}

	public List<MethodTemplate> getMethods() {
		return BaseUtil.removeDuplicateWithOrder ( methods );
	}

	public String getSuperInterfaceNames() {
		if ( superInterfaceNames == null )
			superInterfaceNames = "";
		return superInterfaceNames;
	}

	public void setSuperInterfaceNames( String superInterfaceName ) {
		this.superInterfaceNames = superInterfaceName;
	}

	public NameGenerater getNameGenerater() {
		return nameGenerater;
	}

	public LayoutType getLayoutType() {
		return layoutType;
	}

	public void setLayoutType( LayoutType layoutType ) {
		this.layoutType = layoutType;
	}

	public String getHostPackage() {
		return null;
	}

	public String getAnnotation() {
		return annotation;
	}

	public boolean isUseRoboGuice() {
		return useRoboGuice;
	}

	public void setUseRoboGuice( boolean useRoboGuice ) {
		this.useRoboGuice = useRoboGuice;
	}
}
